LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;


ENTITY execute IS
PORT
	(
		clk   : IN STD_LOGIC;
		
		op1   : IN unsigned(31 downto 0);
		op2   : IN unsigned(31 downto 0);
		inst  : in unsigned(31 downto 0);
		
		result : out unsigned(127 downto 0);
		target_reg_out : out unsigned(1 downto 0);
		target_reg_valid : out std_logic;
		
		zeroflag_out : out std_logic
	);
END execute;



ARCHITECTURE bhv OF execute IS

  signal inst_buffer : unsigned (31 downto 0) := (others => '0');

  type t_reg is array(0 to 3) of unsigned(31 downto 0);
  signal target_reg : t_reg := (others => (others => '0'));
  signal target_reg_nr2 : unsigned(1 downto 0) := (others => '0');
  
  signal target_reg_valid_buffer : std_logic := '0';
  
  signal zeroflag : std_logic := '0';

BEGIN
  
  
 
	process (clk)
	begin
	 if rising_edge(clk) then
	     
	     
	   inst_buffer <= inst;
	     
	   case inst_buffer(27 downto 24) is  
	     
			-- load imidiate high + low
			--when "0001" =>
			--	if inst_buffer(28)='0' then
			--		target_reg(0)<= target_reg(0)(31 downto 16) & inst_buffer(15 downto 0);
			--	else
			--		target_reg(0)<=  inst_buffer(15 downto 0) & target_reg(0)(15 downto 0);
			--	end if;
			--	target_reg_nr2 <= "00";
				
				
			-- add
			 when "0010" =>
				target_reg(0)<=op1+op2;
				target_reg_nr2 <= "00";


			 -- sub + imidiate
			 when "0011" =>
				target_reg(0)<=op1-op2;
				target_reg_nr2 <= "00";
																			   
				if (inst_buffer(28)='0' and op1=op2) or (inst_buffer(28)='1' and op1=inst_buffer(7 downto 0)) then
					zeroflag <= '1';
				 else
					zeroflag <= '0';
				end if;		
				
				--if op1<op2 then
				--	carryflag <= '1';
				--else
				--	carryflag <= '0';
				--end if;	
				
			
			 -- switch high/low
			 when "0100" =>
				target_reg(1)<= op1(15 downto 0) & op1(31 downto 16);
				target_reg_nr2 <= "01";							   
		
		
			 -- shift
			 when "0101" =>
				target_reg_nr2 <= "01";
				if op2(5)='1' then
					target_reg(1)<=op1 srl to_integer(op2(4 downto 0));	
				else
					target_reg(1)<=op1 sll to_integer(op2(4 downto 0));	
				end if;
			
			
			 -- logicals
			 when "0111" =>
				target_reg(2)<=op1 and op2;
				target_reg_nr2 <= "10";
		
			 when "1000" =>
				target_reg(2)<=op1 or op2;
				target_reg_nr2 <= "10";
		
			 when "1001" =>
				target_reg(2)<=op1 xor op2;
				target_reg_nr2 <= "10";
				
			 -- mul
			 when "1011" =>
				target_reg(3)<=op1(15 downto 0) * op2(15 downto 0);
				target_reg_nr2 <= "11"; 
				
			 when others =>
	 
	   end case;
	   
	   if inst_buffer(27 downto 24)="0000" then
	     target_reg_valid_buffer <= '0';
	   else
	     target_reg_valid_buffer <= '1'; 
     end if;

	 end if;
	end process;
	
	result(31 downto 0) <= target_reg(0);
	result(63 downto 32) <= target_reg(1);
	result(95 downto 64) <= target_reg(2);
	result(127 downto 96) <= target_reg(3);
	
	target_reg_out <= target_reg_nr2;
	target_reg_valid <= target_reg_valid_buffer;

	zeroflag_out <= zeroflag;

END bhv;



